﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ServiceModel.Channels;
using System.Xml;
using System.IO;
using System.ServiceModel;
using System.Runtime.Serialization;
using HomeFramework.Model;
using System.Security.Policy;
using System.Diagnostics;
using System.Runtime.Remoting.Lifetime;
using System.ServiceModel.Description;
using HomeFramework.Core;
using System.Reflection;
using System.ServiceModel.Routing;
using System.Xml.Serialization;

namespace HomeFramework.Services
{
    public static partial class HomeFrameworkEngine
    {
        private static Binding NewTempBinding(string type)
        {
            //var assembly = AppDomain.CurrentDomain.GetAssemblies().SingleOrDefault(a => a.GetType(type) != null);
            //var binding = (Binding)assembly.CreateInstance(type);
            //return binding;

            return new NetNamedPipeBinding();
        }

        /// <summary>
        /// Returns the list of endpoint of the current homeframework service
        /// </summary>
        /// <returns></returns>
        private static ServiceEndpoint[] getHomeFrameworkEndpoints()
        {
            using (var temp = new ServiceHost(typeof(RoutingService), new Uri("http://localhost/fakepath"), new Uri("net.tcp://localhost/fakepath"), new Uri("net.pipe://localhost/fakepath")))
            {
                return temp.Description.Endpoints.ToArray();
            }
        }

        private static string RandomPath(Binding binding)
        {
            return binding.Scheme + "://localhost/" + Guid.NewGuid().ToString();
        }
        
        private static Message CloneEnvelope(Message a, XmlReader r)
        {
            var risp = Message.CreateMessage(a.Version, a.Headers.Action, r);

            foreach (MessageHeader header in a.Headers)
                risp.Headers.Add(header);

            foreach (var prop in a.Properties)
                risp.Properties.Add(prop.Key, prop.Value);

            return risp;
        }

        private static Message NewEnvelope(XmlReader r)
        {
            return Message.CreateMessage(MessageVersion.None, string.Empty, r);
        }

        private static string MessageVersionToString(MessageVersion arg)
        {
            var props = typeof(MessageVersion).GetProperties(BindingFlags.Static | BindingFlags.Public);
            var prop = props.Where(p=> p.Name != "Default").Single(p => ((MessageVersion)p.GetValue(null, null)) == arg);
            var risp = prop.Name;
            return risp;
        }

        private static MessageVersion MessageVersionFromString(string arg)
        {
            var props = typeof(MessageVersion).GetProperties(BindingFlags.Static | BindingFlags.Public);
            var prop = props.Where(p => p.Name != "Default").Single(p => p.Name == arg);
            var risp = prop.GetValue(null, null);
            return (MessageVersion)risp;
        }

        //#region HandlerUtilities(APPDOMAIN)

        //internal class DomainHandlerUtility : MarshalByRefObject, IDisposable
        //{
        //    private AppDomain privateDomain;
        //    private Handler s;
        //    private AssemblyHandlerUtility assemblyHandler;

        //    public DomainHandlerUtility(Handler h)
        //    {
        //        s = h;
        //        privateDomain = AppDomain.CreateDomain(Guid.NewGuid().ToString(), new Evidence(AppDomain.CurrentDomain.Evidence), AppDomain.CurrentDomain.SetupInformation);
        //        assemblyHandler = (AssemblyHandlerUtility)privateDomain.CreateInstanceAndUnwrap(typeof(AssemblyHandlerUtility).Assembly.FullName, typeof(AssemblyHandlerUtility).FullName);
        //        assemblyHandler.ReadAssembly(s.AssemblyData.ToArray(), s.References.Select(x => x.ReferenceAssembly.ToArray()).ToArray());
        //        Debug.WriteLine("Created DomainHandlerUtility " + privateDomain.FriendlyName);
        //    }

         

        //    public void Dispose()
        //    {
        //        Debug.WriteLine("Disposing DomainHandlerUtility");
        //        s = null;
        //        assemblyHandler.Dispose();
        //        AppDomain.Unload(privateDomain);
        //        Debug.WriteLine("Disposed DomainHandlerUtility");
        //    }
        //}

        //internal class AssemblyHandlerUtility : MarshalByRefObject, IDisposable
        //{
        //    private const int DEFAULT_LIFETIME_IN_SECONDS = 1200;

        //    public override object InitializeLifetimeService()
        //    {
        //        var l = (ILease)base.InitializeLifetimeService();
        //        if (l.CurrentState == LeaseState.Initial)
        //        {
        //            l.InitialLeaseTime = TimeSpan.FromSeconds(DEFAULT_LIFETIME_IN_SECONDS);
        //            l.RenewOnCallTime = TimeSpan.FromSeconds(DEFAULT_LIFETIME_IN_SECONDS);
        //        }

        //        Debug.WriteLine(string.Format("Initialized AssemblyHandlerUtility lifetime at {0}", l.InitialLeaseTime.ToString()));
        //        return l;
        //    }

        //    internal Assembly Assembly { get; private set; }
        //    public void ReadAssembly(byte[] assembly, IEnumerable<byte[]> references)
        //    {
        //        Assembly = Assembly.Load(assembly);

        //        Log.WriteLine(Log.SourceEnum.HomeFrameworkApplication, TraceEventType.Information, "Loaded assembly {0}", Assembly.FullName);

        //        foreach (var b in references)
        //        {
        //            var temp = Assembly.Load(b);
        //            Log.WriteLine(Log.SourceEnum.HomeFrameworkApplication, TraceEventType.Information, "Loaded reference {0}", temp.FullName);
        //        }
        //    }

        //    public void Dispose() { Debug.WriteLine("Disposing AssemblyHandlerUtility"); Assembly = null; }
        //}

        //#endregion
    }
}